package org.myabstract.graph.example;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.myabstract.graph.model.Graph;
import org.myabstract.graph.model.INodeType;
import org.myabstract.graph.model.Node;
import org.myabstract.graph.model.Reference;

public class Test {

	private String extensionName;
	private Graph<INodeType> grp = Graph.instance;

	private AdaptorFilter filter = new AdaptorFilter();
	private AdaptorFilter filterParent = new AdaptorFilter();

	public Test(String extensionName) {
		this.extensionName = extensionName;
		Graph.instance.resetGraph();
	}

	public void createNamespace() {
		Node<INodeType> nodeNamespace;
		IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
		IExtensionPoint point = extensionRegistry
				.getExtensionPoint(this.extensionName);
		IExtension[] extensions = point.getExtensions();

		// need to take a contributor only once
		Map cuplat = new HashMap();
		for (int i = 0; i < extensions.length; i++) {
			IContributor contributor = extensions[i].getContributor();
			Set contrExt = (Set) cuplat.get(contributor);
			if (contrExt == null) {
				contrExt = new HashSet();
				cuplat.put(contributor, contrExt);
			}
			contrExt.add(extensions[i]);
		}

		Set entry = cuplat.entrySet();
		for (Iterator it = entry.iterator(); it.hasNext();) {
			Map.Entry e = (Map.Entry) it.next();

			nodeNamespace = new Node<INodeType>(new Namespace((IContributor) e
					.getKey()));

			AdaptorArc namespaceArc = new AdaptorArc();
			namespaceArc.addToPath(nodeNamespace);

			nodeNamespace.setChildrenFilter(filter);
			nodeNamespace.setParentFilter(filterParent);

			grp.addNode(nodeNamespace);

			Set extensionList = (Set) e.getValue();
			for (Iterator t = extensionList.iterator(); t.hasNext();) {
				IConfigurationElement[] configFactoryElements = ((IExtension) t
						.next()).getConfigurationElements();
				this.createNodes(nodeNamespace,configFactoryElements);
			}
		}
	}

	private void createNodes(Node<INodeType> nodeNamespace,
			IConfigurationElement[] configFactoryElements) {
		
		AdaptorArc namespaceArc;
		
		for (int j = 0; j < configFactoryElements.length; j++) {
			if (configFactoryElements[j].getName().equalsIgnoreCase("factory")) {
				Node<INodeType> node = new Node<INodeType>(new Factory(
						configFactoryElements[j]));
				namespaceArc=new AdaptorArc();
				try {
					Reference<INodeType, INodeType> refNF = new Reference<INodeType, INodeType>(
							node, nodeNamespace);
					
					namespaceArc.addToPath(nodeNamespace);
					namespaceArc.addToPath(node);

					refNF.addArc(namespaceArc); 

					node.addReference(refNF);

//					node.setChildrenFilter(filter);
//					node.setParentFilter(filterParent);

					nodeNamespace.addReference(refNF);

				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				grp.addNode(node);

				IConfigurationElement[] configAdapterElements = configFactoryElements[j]
						.getChildren();

				for (int k = 0; k < configAdapterElements.length; k++) {
					Node<INodeType> nodeAdapter = new Node<INodeType>(
							new Adaptor(configAdapterElements[k]));

					try {
						Reference<INodeType, INodeType> refAF = new Reference<INodeType, INodeType>(
								nodeAdapter, node);

						nodeAdapter.addReference(refAF);

						// nodeAdapter.setChildrenFilter(filter);
						// nodeAdapter.setParentFilter(filterParent);

						namespaceArc.addToPath(nodeAdapter);
						
						refAF.addArc(namespaceArc);

						node.addReference(refAF);

					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					grp.addNode(nodeAdapter);
				}
			}
		}
	}

}
